﻿//创建时间: 2011-7-15
//创建作者: 李 城
//功能说明: cms系统 缓存操作类
//最后修改: 2011-7-15
// 缓存管理的思路:
//    有全局的 Dictionary<string, object> 来保存全部的缓存，缓存的读、写、删操作都需要通过 lockCacheManage 变量来锁定
//    
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Caching;
using System.Web;
using System.Collections;
using System.Text.RegularExpressions;
using Microsoft.Practices.EnterpriseLibrary.Caching;
using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;
using Yorkg.CMS.Plugin;
using Yorkg.Base;

namespace Yorkg.CMS.Cache
{
    /// <summary>
    /// 缓存操作类
    /// </summary>
    public class CacheManage_dictionary : Yorkg.CMS.Plugin.ICache
    {
        #region 基本变量
        /// <summary>
        /// 缓存操作的企业类库
        /// </summary>
        private CacheManager m_CacheBase = CacheFactory.GetCacheManager();
        /// <summary>
        /// 默认的缓存时间
        /// </summary>
        private const double m_DurationSecond = 60 * 5;
        /// <summary>
        /// 最大的缓存数目
        /// </summary>
        private int mintMaxCacheNum = 100;
        /// <summary>
        /// 缓存基本操作的lock
        /// </summary>
        private static readonly object lockCacheManage = new object();
        #endregion

        #region 继承借口的方法
        /// <summary>
        /// 增加一个缓存对象[ 锁定lockCacheManage 增加缓存 更新缓存key ]
        /// </summary>
        /// <param name="strKey">主键</param>
        /// <param name="valueObj">cache值</param>
        /// <param name="duration">以秒为单位</param>
        /// <returns></returns>
        public bool Save(string strKey, object objValue, double durationSecond)
        {
            if (IsUnValidKey(strKey, objValue))
                return false;
            //清理缓存，将多余的缓存删掉
            FlushChace();
            //保存缓存
            lock (lockCacheManage)
            {
                m_CacheBase.Add(strKey, //key
                                objValue, //value
                                Microsoft.Practices.EnterpriseLibrary.Caching.CacheItemPriority.Normal,
                                null,
                                new AbsoluteTime(TimeSpan.FromSeconds((durationSecond <= 0 ? m_DurationSecond : durationSecond))));
            }
            //添加key
            AddKey(strKey);
            return true;
        }
        /// <summary>
        /// 判断缓存对象是否存在
        /// </summary>
        /// <param name="strKey">主键</param>
        /// <returns></returns>
        public bool IsExist(string strKey)
        {
            if (IsUnValidKey(strKey))
                return false;
             //保存缓存
            lock (lockCacheManage)
            {
                return m_CacheBase.Contains(strKey);
            }
        }
        /// <summary>
        /// 读取缓存对象[ 锁定lockCacheManage]
        /// </summary>
        /// <param name="strKey">主键</param>
        /// <returns></returns>
        public object Read(string strKey)
        {
            if (IsUnValidKey(strKey))
                return null;
            lock (lockCacheManage)
            {
                return m_CacheBase.GetData(strKey);
            }
        }
        /// <summary>
        /// 删除一个缓存对象 [ 锁定lockCacheManage 删除缓存 更新缓存key ]
        /// </summary>
        /// <param name="strKey">主键</param>
        /// <returns></returns>
        public void Remove(string strKey)
        {
            if (IsUnValidKey(strKey))
                return ;
            if (m_CacheBase.Contains(strKey))
            {
                lock (lockCacheManage)
                {
                    if (m_CacheBase.Contains(strKey))
                    {
                        m_CacheBase.Remove(strKey);
                    }
                }
            }
        }
        /// <summary>
        /// 清除所有缓存对象   [ 锁定lockCacheManage 清除所有缓存 ]
        /// </summary>
        public void Clear()
        {
            if (m_CacheBase.Count > 0)
            {
                lock (lockCacheManage)
                {
                    if (m_CacheBase.Count > 0)
                    {
                        m_CacheBase.Flush();
                    }
                }
            }
        }
        /// <summary>
        /// 根据设置的正则表达式清除缓存对象
        /// </summary>
        /// <param name="pattern">正则表达式</param>
        public void RemoveByRegexp(string pattern)
        {
            if (IsUnValidKey(pattern))
                return;
            if (m_CacheBase.Contains(CacheKeys.mAllCacheKeys))
            {
                Dictionary<string, int> oDicKeys;
                object objKeys = m_CacheBase.GetData(CacheKeys.mAllCacheKeys);
                if (objKeys != null && objKeys is Dictionary<string, int>)
                {
                    oDicKeys = objKeys as Dictionary<string, int>;
                    foreach (KeyValuePair<string, int> otemp in oDicKeys)
                    {
                        if (Regex.IsMatch(otemp.Key, pattern, RegexOptions.IgnoreCase))
                            Remove(otemp.Key);
                    }
                }
            }
        }
        #endregion

        #region 内部辅助的方法
        /// <summary>
        /// 判断是否是无效的KEY
        /// </summary>
        /// <param name="strKey"></param>
        /// <returns></returns>
        private bool IsUnValidKey(params object[] Obj)
        {
            foreach (object objTemp in Obj)
            {
                if (Obj == null || (objTemp is string && string.IsNullOrEmpty(Obj.ToString())))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// 添加Key [ 锁定 lockHelperCacheKeys 直接添加key ]
        /// </summary>
        /// <param name="strKey"></param>
        private void AddKey(string strKey)
        {
            if (IsUnValidKey(strKey))
                return;
            if (m_CacheBase.Contains(strKey))
            {
                lock (lockCacheManage)
                {
                    if (m_CacheBase.Contains(strKey))
                    {
                        Dictionary<string, int> oDicKeys;
                        object objDic =  m_CacheBase.GetData(CacheKeys.mAllCacheKeys);
                        if (objDic != null && objDic is Dictionary<string, int>)
                        {
                            oDicKeys = objDic as Dictionary<string, int>;
                        }
                        else
                            oDicKeys = new Dictionary<string, int>();
                        if (oDicKeys.ContainsKey(strKey))
                            return;
                        else
                            oDicKeys.Add(strKey, 0);
                    }
                }
            }
        }
        /// <summary>
        /// 根据缓存的个数限制，清楚多余的缓存
        /// </summary>
        private void FlushChace()
        {
            object obj;
            if (m_CacheBase.Contains(CacheKeys.mAllCacheKeys) && ((obj = m_CacheBase.GetData(CacheKeys.mAllCacheKeys)) is Dictionary<string, int>) )
            {
                lock (lockCacheManage)
                {
                    if (m_CacheBase.Contains(CacheKeys.mAllCacheKeys) && ((obj = m_CacheBase.GetData(CacheKeys.mAllCacheKeys)) is Dictionary<string, int>))
                    {
                        Dictionary<string, int> oDicKeys = obj as Dictionary<string, int>;
                        if (oDicKeys.Count >= mintMaxCacheNum)
                        {
                            int intRemove = oDicKeys.Count - mintMaxCacheNum + 1;
                            ArrayList oArray = new ArrayList();
                            foreach (KeyValuePair<string, int> otemp in oDicKeys)
                            {
                                if (intRemove <= 0)
                                    break;
                                m_CacheBase.Remove(otemp.Key);
                                oArray.Add(otemp.Key);
                            }
                            for(int index = 0;index<oArray.Count;index++)
                            {
                                oDicKeys.Remove(oArray[index].ToString());
                            }
                        }
                    }
                }
            }
        }
        #endregion
    }
}
